<?php

namespace App\Library;

/** 腾讯 无服务器云函数接口调用 */
class TcScfUtil
{
    private $secretId;
    private $secretKey;
    private $region = "";               // 地域
    private $service;                       // 产品服务名
    private $host;      // 产品默认域名
    private $timestamp;
    private $date;
    private $version;                // api版本号
    private $signatureMethod = "TC3-HMAC-SHA256";   // 签名方法
    private $httpRequestMethod = "POST";            // 请求类型
    private $canonicalUri = "/";
    private $signedHeaders = "content-type;host";
    private $canonicalHeaders;
    private $url;// 请求地址
    private $returnData;
    static $object;

    public function __construct($secretId, $secretKey, $type = 'bill')
    {
        if($type == 'bill'){
            $this->getBill();
        }elseif($type == 'partner'){
            $this->getPartner();
        }elseif($type == 'vod'){
            $this->getVod();
        }
        $this->secretId = $secretId;
        $this->secretKey = $secretKey;
        $this->canonicalHeaders = "content-type:application/json\nhost:{$this->host}\n";
    }

    public function getBill(){
        $this->service = 'billing';
        $this->host = "billing.tencentcloudapi.com";
        $this->version = "2018-07-09";
        $this->url = 'https://billing.tencentcloudapi.com';
    }

    public function getPartner(){
        $this->service = 'partners';
        $this->host = 'partners.tencentcloudapi.com';
        $this->version = '2018-03-21';
        $this->url = 'https://partners.tencentcloudapi.com';
    }

    public function getVod(){
        $this->service = 'vod';
        $this->host = 'vod.tencentcloudapi.com';
        $this->version = '2018-07-17';
        $this->url = 'https://vod.tencentcloudapi.com';
    }

    /**
     * @return TcScfUtil
     */
    public static function getInstance(){
        $param = func_get_args();
        $md5 = md5(implode("", $param));
        if(empty(self::$object[$md5])){
            self::$object[$md5] = new self($param[0], $param[1], isset($param[2]) ? $param[2] : "bill");
        }
        return self::$object[$md5];
    }

    // 请求接口的签名准备过程
    public function preSignPrepare($data){
        $this->timestamp = time();
        $this->date = date("Y-m-d", $this->timestamp);

        // ************* 步骤 1：拼接规范请求串 *************
        $hashedRequestPayload = strtolower(bin2hex(hash("sha256", $data, true)));
        $canonicalRequest = "{$this->httpRequestMethod}\n{$this->canonicalUri}\n\n{$this->canonicalHeaders}\n{$this->signedHeaders}\n{$hashedRequestPayload}";

        // ************* 步骤 2：拼接待签名字符串 *************
        $credentialScope = "{$this->date}/{$this->service}/tc3_request";
        $hashedCanonicalRequest = strtolower(bin2hex(hash("sha256", $canonicalRequest, true)));
        $stringToSign = "{$this->signatureMethod}\n{$this->timestamp}\n{$credentialScope}\n{$hashedCanonicalRequest}";

        // ************* 步骤 3：计算签名 *************
        $secretDate = hash_hmac('sha256', $this->date, "TC3".$this->secretKey, true);
        $secretService = hash_hmac('sha256', $this->service, $secretDate, true);
        $secretSigning = hash_hmac('sha256', "tc3_request", $secretService, true);
        $signature = strtolower(bin2hex((hash_hmac('sha256', $stringToSign, $secretSigning, true))));
        $authorization = "{$this->signatureMethod} Credential={$this->secretId}/{$credentialScope}, SignedHeaders={$this->signedHeaders}, Signature={$signature}";

        return $authorization;
    }

    // 请求接口返回结果
    public function getRequest($action, $data, $isArray = false){
        $option = $isArray ? JSON_UNESCAPED_UNICODE : JSON_UNESCAPED_UNICODE|JSON_FORCE_OBJECT;
        $requestData = json_encode($data, $option);
        // 组装请求头
        $header[] = "Authorization:".$this->preSignPrepare($requestData);
        $header[] = "Host:{$this->host}";
        $header[] = "Content-Type:application/json";
        $header[] = "X-TC-Action:{$action}";
        $header[] = "X-TC-Timestamp:{$this->timestamp}";
        $header[] = "X-TC-Version:{$this->version}";
        $header[] = "X-TC-Region:{$this->region}";

        $res = json_decode($this->curl($this->url, $requestData, $header, 300),true);
        if(isset($res["Response"]["Error"])){
            $this->returnData = \App\Http\Config\ErrorCode::$admin_enum["fail"];
            $this->returnData["msg"] = $res["Response"]["Error"]["Message"];
            $this->returnData["error"] = $res["Response"]["Error"];
        }else{
            $this->returnData = \App\Http\Config\ErrorCode::$admin_enum["success"];
            $this->returnData["data"] = isset($res["Response"]) ? $res["Response"] : $res;
        }
        return $this->returnData;
    }

    public function curl($url, $data = "", $header = ['Content-Type: application/json'], $timeout = 60)
    {
        $ch = curl_init($url);
        if(empty($data)){
            curl_setopt($ch, CURLOPT_HTTPGET, 1);
        }else {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
        if(!empty($header)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        }
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
        $output = curl_exec($ch);
        $errno = curl_errno($ch);
        if ($errno) {
            return false;
        }
        curl_close($ch);
        return $output;
    }

    // 获取账户余额
    public function describeAccountBalance(){
        $action = "DescribeAccountBalance"; //
        return $this->getRequest($action, []);
    }

    // 查询客户级别
    public function describeAgentClientGrade($id){
        $action = "DescribeAgentClientGrade"; //
        return $this->getRequest($action, ['ClientUin' => $id]);
    }

    // 提交客户代付
    public function agentPayDeals($data){
        $action = "AgentPayDeals"; //
        return $this->getRequest($action, $data, true);
    }

    // 查询客户订单 - 代付订单
    public function describeAgentPayDeals($data){
        $action = "DescribeAgentPayDeals";
        return $this->getRequest($action, $data, true);
    }

    // 查询客户订单 - 代付和自付订单
    public function describeAgentDealsCache($data){
        $action = "DescribeAgentDealsCache";
        return $this->getRequest($action, $data, true);
    }

    // 代理商业务员查询接口
    public function describeSalesmans($data){
        $action = "DescribeSalesmans";
        return $this->getRequest($action, $data, true);
    }

    // 查询已审核客户列表
    public function describeAgentAuditedClients($data){
        $action = "DescribeAgentAuditedClients";
        return $this->getRequest($action, $data, true);
    }

    // 查询待审核客户列表
    public function describeAgentClients($data){
        $action = "DescribeAgentClients";
        return $this->getRequest($action, $data, true);
    }

    // 审核客户
    public function auditApplyClient($data){
        $action = "AuditApplyClient";
        return $this->getRequest($action, $data, true);
    }

    // 查询客户余额
    public function describeClientBalance($data){
        $action = "DescribeClientBalance";
        return $this->getRequest($action, $data, true);
    }

    // 给客户转账
    public function agentTransferMoney($data){
        $action = "AgentTransferMoney";
        return $this->getRequest($action, $data, true);
    }

    // 查询业务明细
    public function describeAgentBills($data){
        $action = "DescribeAgentBills";
        return $this->getRequest($action, $data, true);
    }

    // 云点播 创建分类  https://cloud.tencent.com/document/product/266/31772
    public function vodCreateClass($data){
        $action = "CreateClass"; // 接口名
        return $this->getRequest($action, $data);
    }

    // 云点播 创建指定时间点截图模板  https://cloud.tencent.com/document/product/266/37786
    public function vodCreateSnapshotByTimeOffsetTemplate($data){
        $action = "CreateSnapshotByTimeOffsetTemplate"; // 接口名
        return $this->getRequest($action, $data);
    }
}